package com.boot.redisson;


import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Aspect
@Component
@Slf4j
public class DistributedLockHandler {

    private final RedissonClient redisson;

    public DistributedLockHandler(RedissonClient redisson) {
        this.redisson = redisson;
    }

    @SneakyThrows
    @Around("@annotation(distributedLock)")
    public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
        log.info("[开始]执行RedisLock环绕通知,获取Redis分布式锁开始");
        RLock lock;
        if (StringUtils.hasText(distributedLock.value())) {
            lock = redisson.getLock(distributedLock.value());
        } else {
            lock = redisson.getLock(joinPoint.toString());
        }
        try {
            if (distributedLock.leaseTime() == -1) {
                lock.lock();
            } else {
                lock.lock(distributedLock.leaseTime(), distributedLock.unit());
            }
            log.info("获取Redis分布式锁[成功]，开始执行业务逻辑...");
        } catch (Throwable throwable) {
            log.error("获取Redis分布式锁[异常]，加锁失败", throwable);
            throw throwable;
        }
        try {
            return joinPoint.proceed();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("释放Redis分布式锁[成功]，解锁完成，结束业务逻辑");
            } else {
                log.error("释放Redis分布式锁[失败]，锁不被本线程持有");
            }
        }
    }
}
